package Commnads;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.eclipse.swt.widgets.ProgressBar;

import DB.AlgoDBMan;
import DB.DBmanager;
import DB.DirDBMan;
import DB.LogDBMan;
import Listening.Listening;
import TagAlgorithms.TagAlgorithms;
import UI.OurGUI;

/**
 * This class is the main bridge, and it connect between all packages.
 * it's contains all the commands, and all the commands would be keep in {@link HashMap}. 
 * we also holding here  {@link Executor} ThreadPool to manage he threads,
 * and {@link HashMap}s to keep all information. 
 * @author DROR
 */

public class Commands 
{
	private ConcurrentHashMap<String,Command> commandsMap; 
	private int numOfThreads;
	private DBmanager filesMan;
	private LogDBMan sysLog;
	private Executor executor;
	private Listening listening;
	private AlgoDBMan algoMan;
	private DirDBMan dirMan;
	private HashMap<String,TagAlgorithms> allAlgos;
	private HashMap<String,String> algosNamesHash;


	/**
	 * This function sets its member listening
	 * @param listening reference to {@link Listening} class
	 */
	public void setListening(Listening listening)
	{
		this.listening = listening;
	}

	/**
	 * Constructor
	 * @param fileTag {@link DBmanager} The table of files and tags
	 * @param sysLog2 {@link LogDBMan} The table of the log
	 * @param algo {@link AlgoDBMan} The table of algorithms
	 * @param dirExp {@link DirDBMan} The table of directories and regular expressions
	 */
	public Commands(DBmanager fileTag, LogDBMan sysLog2, AlgoDBMan algo, DirDBMan dirExp) 
	{
		allAlgos= new HashMap<String, TagAlgorithms>();
		commandsMap=new ConcurrentHashMap<String,Command>();
		numOfThreads = 5;
		executor = Executors.newFixedThreadPool (numOfThreads);
		filesMan = fileTag;
		algoMan = algo;
		sysLog=sysLog2;
		dirMan = dirExp;
		algosNamesHash = new HashMap<String, String>();
		insertDefualtExprs();
		insertToAlgosNamesHash();
		initAllAlgosHash();

		add( new searchByTagCommand());
		add( new startListenCommand());
		add( new stopListenCommand());
		add( new addTagCommand());
		add( new autoTaggingCommand());
		add( new getLogFile());
		add( new selectDir());
		add( new removeDir());
		add( new  deleteTagCommand());
		add( new insertToLogCommand());
		add( new removeFileCommand());
		add( new cleanSystemCommand());
		add( new getDirectoriesCommand());
		add( new removeExpressionCommand());
		add( new addExpressionCommand());
		add( new getTagCommand());
		add( new getAllTagsCommand());
		add( new getAllExpressionsCommand());
		add( new assignExpToDirCommand());
		add( new dynamicLoadingCommand());
		add( new startInitCommand());
		add( new stopInitCommand());
		add( new pauseInitCommand());
		add( new resumeInitCommand());
		add( new getSelectedAlgos());
		add( new getAllAlgos());
		add (new removeTagsFromFileCommand());
	}
	public Commands(){}

	/**
	 * Interface class that include all function that each command must implement
	 * @author DROR
	 */
	public interface Command  
	{
		public void execute();
		public Command clone();
		public String getKey();
	}

	/**
	 * This function pulling a {@link Command} from the {@link HashMap} 
	 * @param command {@link String} The key of the command
	 * @return The requested Command
	 */
	public Command getCom(String command)
	{
		if(commandsMap.get(command)!= null)
			return commandsMap.get(command).clone();
		else 
			return null;
	}

	/**
	 * This function adding a new command to the {@link HashMap}
	 * @param c The new {@link Command}
	 */
	private void add(Command c)
	{
		commandsMap.put(c.getKey(), c);
	}

	/**
	 * This function sets the number of threads in the {@link ThreadPoolExecutor} 
	 * @param numOfThreads The number
	 */
	public void setNumOfThreads(int numOfThreads) {
		this.numOfThreads = numOfThreads;
	}

	/**
	 * This function returns the executer
	 * @return {@link Executor} 
	 */
	public  Executor getExecutor() {
		return executor;
	}

	/**
	 * This function inserts the default algorithms to the {@link HashMap}
	 */
	public void insertToAlgosNamesHash()
	{
		algosNamesHash.put("Key words","KeyWords");
		algosNamesHash.put("Ascii file","AsciiFileTag");
		algosNamesHash.put("Size of file","TagBySize");
		algosNamesHash.put("Creation Date","TagByDate");
	}

	/**
	 * This function inserts default expressions to {@link DirDBMan} table
	 */
	public void insertDefualtExprs()
	{
		if (dirMan.getAllExps() == null)
		{
			dirMan.addExp("*.txt");
			dirMan.addExp("*.doc");
			dirMan.addExp("89*");
			dirMan.addExp("*.exe");
		}
	}

	/**
	 * This function returns the description of some algorithm
	 * @param path The path by {@link String} of algorithm's class
	 * @return The description {@link String} of this algorithm 
	 */
	public String getClassDiscription(String path)
	{
		return allAlgos.get(path).getDescription();
	}

	/**
	 * This function checking if a file should be tagged according its expression
	 * @param path The path by {@link String} of the file 
	 * @return {@link Boolean} true or false
	 */
	public boolean checkExpression(String path)
	{
		Path child= Paths.get(path);
		String parent = child.getParent().toString();
		ArrayList<String> pathExp=new ArrayList<String>();
		/* getting all the expressions that had assigned to this directory*/
		if (dirMan.getExps(parent) != null)
			pathExp.addAll(dirMan.getExps(parent));
		/* checking if the expression is valid by PathMatcher */
		FileSystem filesys= FileSystems.getDefault();
		PathMatcher pathm; 
		Path p = child.getName();
		if (pathExp.size() >0)
		{ 
			Iterator<String> it = pathExp.iterator();
			while (it.hasNext())
			{
				String exp = it.next();
				pathm = filesys.getPathMatcher("glob:"+exp);
				if(pathm.matches(p))
					return true; /* we can tagging this file */
			}
			/* this file doesn't match to the expressiond.we don't tagging it */
			return false; 
		}
		return true;
	}


	/**
	 * This function returns algorithm's name
	 * @param path The path by {@link String} of the algorithm's class 
	 * @return {@link String} algorithm's name
	 */
	public String getNameofAlgo(String path)
	{
		return allAlgos.get(path).getAlgName();
	}

	/**
	 * This function initialize the {@link HashMap} that holds all algorithm
	 */
	public void initAllAlgosHash()
	{
		if (algoMan.getAllAlgos()== null)
		{
			algoMan.addAlg("Key words");
			algoMan.addAlg("Ascii file");
			algoMan.addAlg("Size of file");
			algoMan.addAlg("Creation Date");
		}
		getAllAlgos c = new getAllAlgos();
		c.execute();
		ArrayList<String> algs= c.getAlgosArr();
		int size= algs.size();
		for(int i =0;i<size;i++)
		{
			if (i<4)
				setSelectedAlgorithms(algs.get(i), 0);
			else
			{
				setSelectedAlgorithms(algs.get(i), 1);
			}
		}
	}

	/**
	 * This function extracts file's name from his path
	 * @param path The path by {@link String} of file
	 * @return The name by {@link String} of file
	 */
	public String getFileNameFromPath(String path)
	{
		String words[]=path.split("\\\\");
		int len= words.length;
		String last[]=words[len-1].split("\\.");
		return (last[0]);
	}

	/**
	 * This function inserts a new algorithm to the table in {@link AlgoDBMan}
	 * @param alg algorithm's name by {@link String}
	 * @param path algorithm's class path by {@link String}
	 */
	public void insertToAllAlgos(String alg,String path)
	{

		String name= getFileNameFromPath(path);
		algosNamesHash.put(name, alg);
		algoMan.addAlg(path);
		setSelectedAlgorithms(path, 1);		
	}

	/**
	 * This function loading the selected algorithms
	 * @param path The path by {@link String} of algorithm's class
	 * @param selected a flag that telling if it is a new algorithm or a default one
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public void setSelectedAlgorithms(String path, int selected) 
	{
		try
		{
			/* set the folder with my algorithms */
			String folder= "Algorithms";

			if (selected==1) /* set the folder with the path of the new algorithm */
			{
				Path p = Paths.get(path);
				folder=p.getParent().toString();
			}
			File f=new File(folder); 
			URL url = null;
			url = f.toURL();
			URL[] urls=new URL[]{url};
			ClassLoader cl=new URLClassLoader(urls);
			Class<TagAlgorithms> c = null;
			if (selected==1)  /* loading the new algorithm */
			{
				String name= getFileNameFromPath(path);
				c = (Class<TagAlgorithms>) cl.loadClass(name);
			}
			else  /* loading my algorithm */
			{
				String name= algosNamesHash.get(path);
				c = (Class<TagAlgorithms>) cl.loadClass(name);	
			}
			TagAlgorithms a = null;
			a = c.newInstance();
			/* inserting the algorithm  to the HashMap*/
			if (selected==1 || selected ==0)
			{
				allAlgos.put(path, a);
			}
		}
		catch (MalformedURLException e)  {}
		catch (ClassNotFoundException e) {}
		catch (InstantiationException e) {} 
		catch (IllegalAccessException e) {}
	}

	/**
	 * This function calculate the percent of the tagged files for updating the {@link ProgressBar} 
	 * We call to that function from {@link Listening} class.
	 * @return The percent
	 */
	public int getPercent()
	{
		return listening.getPercent();
	}

	/******************************************************
	 * There are all the commands. each command in each class
	 * ****************************************************/


	/**
	 * This class executing the automatic tagging.
	 * First we checking the selected algorithms, and the suit regular expression,
	 * and then tagging the file respectively. 
	 * This Command gets file's path. 
	 */
	public class autoTaggingCommand extends ImpCommand
	{
		public void execute() 
		{       
			ArrayList<String> selcalg= algoMan.getAllChosenAlgo();
			/* checking if some tagging algorithm had been selected */
			if (selcalg!=null)
			{
				String pathFile=  getPathOnString();
				/* checking if the file matching to the selected regular expressions */
				if (checkExpression(pathFile))
				{
					int size = selcalg.size(); 
					int size2;
					for (int i=0;i<size;i++)
					{
						ArrayList<String> a = new ArrayList<String>();
						String f= selcalg.get(i); /* getting the algorithm */
						a= allAlgos.get(f).getTags(pathFile); /* getting the tags */
						size2= a.size();
						for (int j=0;j<size2;j++)
						{
							/* adding the tag to the file*/
							addTagCommand c = (addTagCommand)getCom("add tag");
							c.setTag(a.get(j));
							c.setPathOnString(pathFile);
							String name = getFileNameFromPath(pathFile);
							c.setFile(name);
							c.execute();
						}
					}
				}
			}
		}
		public String getKey() 
		{
			return "auto tag";
		}
		public Command clone() {return new autoTaggingCommand();}
	}

	/**
	 * This class gets an {@link ArrayList} of the selected tagging algorithms,
	 * and inserts it to the match table in DB
	 */
	public class dynamicLoadingCommand extends ImpCommand
	{
		ArrayList<String> algosArr = new ArrayList<String>(); 
		int selected;
		public ArrayList<String> getAlgosArr() {
			return algosArr;
		}

		public void setAlgosArr(ArrayList<String> algosArr) {
			this.algosArr = algosArr;
		}

		public String getKey(){ return "load";} 

		public void execute()
		{		 
			int len = algosArr.size();
			for (int i=0;i<len;i++)
			{
				insertToLogCommand c = new insertToLogCommand();
				c.setOperation("The algorithm  "+algosArr.get(i)+"  had been selected for tagging");
				c.execute();
			}
			algoMan.selectNewAlgo(algosArr);
		}

		public Command clone() {return new dynamicLoadingCommand();}
	}

	/**
	 * This class returns an {@link ArrayList} of all the algorithms in the table in DB
	 */
	public class getAllAlgos extends ImpCommand
	{
		ArrayList<String> algosArr = new ArrayList<String>(); 
		public ArrayList<String> getAlgosArr() {
			return algosArr;
		}

		public void setAlgosArr(ArrayList<String> algosArr) {
			this.algosArr = algosArr;
		}

		public String getKey(){ return "get all algos";} 

		public void execute()
		{		 
			if ( algoMan.getAllAlgos() != null)
				algosArr.addAll(algoMan.getAllAlgos());
		}
		public Command clone() {return new getAllAlgos();}
	}

	/**
	 * This class returns an {@link ArrayList} of all the selected algorithms in the table in DB
	 * the tagging would be done only according those algorithms.
	 */
	public class getSelectedAlgos extends ImpCommand
	{
		ArrayList<String> algosArr = new ArrayList<String>(); 
		public ArrayList<String> getAlgosArr() {
			return algosArr;
		}

		public void setAlgosArr(ArrayList<String> algosArr) {
			this.algosArr = algosArr;
		}

		public String getKey(){ return "get selected algos";} 

		public void execute()
		{		 
			if ( algoMan.getAllChosenAlgo() != null)
				algosArr.addAll(algoMan.getAllChosenAlgo());
		}

		public Command clone() {return new getSelectedAlgos();}
	}

	/**
	 * This class starting the Initialization.
	 * We call from here to Listening class, and starting the initialization via the Tagger
	 */
	private class startInitCommand extends ImpCommand
	{

		public String getKey(){ return "start init";} 
		public void execute()
		{		 
			listening.startInitialization();
		}
		public Command clone() {return new startInitCommand();}
	}

	/**
	 * This class stopping the Initialization.
	 * We call from here to Listening class, and stopping the initialization via the Tagger
	 */
	private class stopInitCommand extends ImpCommand
	{

		public String getKey(){ return "stop init";} 
		public void execute()
		{		 
			listening.stopInitialization();
		}
		public Command clone() {return new stopInitCommand();}
	}

	/**
	 * This class pausing the Initialization.
	 * We call from here to Listening class, and pausing the initialization via the Tagger
	 */
	private class pauseInitCommand extends ImpCommand
	{

		public String getKey(){ return "pause";} 
		public void execute()
		{		 
			listening.pauseInitialization();
		}
		public Command clone() {return new pauseInitCommand();}
	}

	/**
	 * This class resuming the Initialization.
	 * We call from here to Listening class, and resuming the initialization via the Tagger
	 */
	private class resumeInitCommand extends ImpCommand
	{

		public String getKey(){ return "resume";} 
		public void execute()
		{		 
			listening.resumeInitialization();
		}
		public Command clone() {return new resumeInitCommand();}
	}

	/**
	 * This class returns an {@link ArrayList} of all the regular expressions
	 * in the match table in DB
	 */
	public class getAllExpressionsCommand extends ImpCommand
	{
		ArrayList<String> expres = new ArrayList<String>(); 
		public ArrayList<String> getExpressions() {
			return expres;
		}
		public void setExpressions(ArrayList<String> expres) {
			this.expres = expres;
		}
		public String getKey(){ return "get expressions";} 
		public void execute()
		{		 
			if (dirMan.getAllExps() != null)
				expres.addAll(dirMan.getAllExps());
		}
		public Command clone() {return new getAllExpressionsCommand();}
	}

	/**
	 * This class assigning some expressions to selected directory
	 * The Command gets an {@link ArrayList} of expressions and directory, and inserts
	 * them to DB respectively
	 */
	public class assignExpToDirCommand extends ImpCommand
	{
		ArrayList<String> expres = new ArrayList<String>(); 
		public ArrayList<String> getExpressions() {
			return expres;
		}
		public void setExpressions(ArrayList<String> expres) {
			this.expres = expres;
		}
		public String getKey(){ return "assign";} 
		public void execute()
		{		 
			Iterator<String> it = expres.iterator();
			while (it.hasNext())
				dirMan.addRegExToDir(it.next(), getPathOnString());
		}
		public Command clone() {return new assignExpToDirCommand();}
	}

	/**
	 * This class returns an {@link ArrayList} of all the tags
	 * in the match table in DB
	 */
	public class getAllTagsCommand extends ImpCommand
	{
		ArrayList<String> tags = new ArrayList<String>(); 
		public ArrayList<String> getTags() {
			return tags;
		}
		public void setTags(ArrayList<String> tags) {
			this.tags = tags;
		}
		public String getKey(){ return "get tags";} 
		public void execute()
		{		 
			if (filesMan.getAllTags() != null)
				tags.addAll(filesMan.getAllTags());
		}
		public Command clone() {return new getAllTagsCommand();}
	}

	/**
	 *  This class cleaning the table of tags and files in DB.
	 *  All the tagged files aren't tagged anymore. 
	 */
	public class cleanSystemCommand extends ImpCommand
	{

		public String getKey(){ return "clean";} 
		public void execute()
		{	
			insertToLogCommand c = new insertToLogCommand();
			c.setOperation("The System had cleaned");
			c.execute();
			filesMan.delAllTags();
			filesMan.delAllFiles();
		}
		public Command clone() {return new cleanSystemCommand();}
	}


	/**
	 *  This class executing the main search.
	 *  The Command gets a {@link Set} of tags that supposed belong to the file, and a 
	 *  a {@link Set} of tags that aren't supposed belong to the file.
	 *  The Command returns an {@link ArrayList} of the match files
	 */
	public class searchByTagCommand extends ImpCommand
	{
		Set<String> includedtags = new HashSet<String>();
		Set<String> notIncludedtags= new HashSet<String>();
		ArrayList<String> files = new ArrayList<String>();

		public Set<String> getIncludedtags() {
			return includedtags;
		}
		public void setIncludedtags(Set<String> includedtags) {
			this.includedtags = includedtags;
		}
		public Set<String> getNotIncludedtags() {
			return notIncludedtags;
		}
		public void setNotIncludedtags(Set<String> notIncludedtags) {
			this.notIncludedtags = notIncludedtags;
		}
		public ArrayList<String> getFiles() {
			return files;
		}
		public void setFiles(ArrayList<String> files) {
			this.files = files;
		}


		public String getKey(){ return "search by tag";} 
		public void execute()
		{	
			Set<String> setfiles = filesMan.getFileByYesNoTags(includedtags, notIncludedtags);
			if (setfiles != null)
				files.addAll(setfiles);
		}
		public Command clone() {return new searchByTagCommand();}
	}

	/**
	 * This class starting the listening.
	 * We call from here to Listening class, and starting the listening via the Listener
	 */
	private class startListenCommand extends ImpCommand
	{

		public String getKey(){ return "start";} 
		public void execute() 
		{
			listening.startListening();
		}
		public Command clone() {return new startListenCommand();}
	}

	/**
	 * This class stopping the listening.
	 * We call from here to Listening class, and stopping the listening via the Listener.
	 */
	private class stopListenCommand extends ImpCommand
	{
		public String getKey(){ return "stop";}
		public void execute()
		{
			listening.stopListening();
		}
		public Command clone() {return new stopListenCommand();}
	}

	/**
	 * The class adding a new tag to file
	 * The Command gets a tag, name of file, and path of file, and inserts it to the
	 * match table in DB  
	 */
	public class addTagCommand extends ImpCommand
	{
		public void execute() 
		{       
			OurGUI.flag=1;
			insertToLogCommand c = new insertToLogCommand();
			c.setOperation("The file  "+getPathOnString()+"  had been tagged with the tag "+getTag());
			c.execute();
			filesMan.addTagToFile(getFile(),getTag(), getPathOnString());
		}
		public String getKey() 
		{
			return "add tag";
		}
		public Command clone() {return new addTagCommand();}
	}

	/**
	 * This class returns the Log
	 * The Command gets the log from the match table in DB, and show it on GUI.
	 * the log composed of The  an {@link ArrayList} of operations. 
	 */
	public class getLogFile extends ImpCommand
	{
		ArrayList<String> opers = new ArrayList<String>();
		public ArrayList<String> getOpers() {
			return opers;
		}
		public void setOpers(ArrayList<String> opers) {
			this.opers = opers;
		}
		public Command clone() {return new getLogFile();}
		public void execute() 
		{
			if (sysLog.getLog() != null)
				opers.addAll(sysLog.getLog());		
		}
		public String getKey() {
			return "get log";
		}
	}

	/**
	 * This class adding a new directory and all it sub-directories to the match table in DB.
	 * We also add all of them to the HashMap in Listening class.
	 * The Command get the {@link Path} of the directory
	 */
	public class selectDir extends ImpCommand
	{
		public Command clone() { return new selectDir();}

		public void execute() 
		{
			try 
			{
				insertToLogCommand c = new insertToLogCommand();
				c.setOperation("The directory  "+getPathOnString()+"   had added to listening");
				c.execute();
				Path p = getPath();
				listening.addDir(p);
				/* visiting through the directory and adding it's childs */
				Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
					public FileVisitResult preVisitDirectory(Path dir) 
					{	
						dirMan.addDir(dir.toString());
						return FileVisitResult.CONTINUE;
					}
				});
			} 
			catch (IOException e) {}
		}
		public String getKey() 
		{
			return "select dir";
		}
	}

	/**
	 *  This class removing a directory and all it sub-directories from the match table in DB.
	 *  We also remove all of them from the HashMap in Listening class.
	 *  The Command get the {@link Path} of the directory
	 */
	public class removeDir extends ImpCommand
	{
		int flag=0;
		public int getFlag() {
			return flag;
		}
		public void setFlag(int flag) {
			this.flag = flag;
		}
		public Command clone() { return new removeDir();}
		public void execute() 
		{
			if (flag==1)
			{
				insertToLogCommand c = new insertToLogCommand();
				c.setOperation("The directory  "+getPathOnString()+"  had removed from listening");
				c.execute();
			}
			if (flag==0)
				filesMan.deleteFile(getPathOnString());
			dirMan.deleteDir(getPathOnString());
		}
		public String getKey() {
			return "remove dir";
		}
	}

	/**
	 * This class deleting a tag from file
	 * According to manual remove tagging, we gets a tag,and {@link Path} of the file
	 * and removing the tag from the match table in DB
	 */
	public class deleteTagCommand extends ImpCommand
	{
		public Command clone() {return new deleteTagCommand ();
		}
		public void execute() 
		{
			insertToLogCommand c = new insertToLogCommand();
			c.setOperation("The tag  "+getTag()+"  had been removed from the file: "+getPathOnString());
			c.execute();
			filesMan.delTagFromFile(getTag(),getPathOnString());
		}

		public String getKey() {	
			return "delete tag";
		}
	}

	/**
	 * This class inserts an new operation to the Log
	 * When we gets an event, we reporting about it to the log.
	 * The operations inserted to Log table in DB
	 */
	public class insertToLogCommand extends ImpCommand
	{
		String operation;
		public String getOperation() {
			return operation;
		}
		public void setOperation(String operation) {
			this.operation = operation;
		}
		public Command clone() {
			return new insertToLogCommand();
		}
		public void execute() {
			java.util.Date date = new java.util.Date();
			java.sql.Timestamp tstamp = new java.sql.Timestamp( date.getTime() );
			String time = tstamp.toString();
			sysLog.addEvent(time+"      "+operation);
		}

		public String getKey() {	
			return "insert to log";
		}
	}

	/**
	 * This class deleting a file
	 * The Command gets the {@link Path} of the file, and removing it from the match table in DB
	 */
	public class removeFileCommand extends ImpCommand
	{
		public Command clone() {
			return new removeFileCommand();
		}
		public void execute() {
			filesMan.deleteFile(getPathOnString());
		}

		public String getKey() {	
			return "remove file";
		}
	}

	/**
	 * This class returns an {@link ArrayList} of all the directories in the match table in DB.
	 */
	public class getDirectoriesCommand extends ImpCommand
	{
		ArrayList<String> dirs = new ArrayList<String>(); 

		public ArrayList<String> getDirs() {
			return dirs;
		}
		public void setDirs(ArrayList<String> dirs) {
			this.dirs = dirs;
		}
		public Command clone() {
			return new getDirectoriesCommand();
		}
		public void execute() 
		{
			if (dirMan.getAllDirs() != null)
				dirs.addAll(dirMan.getAllDirs());
		}

		public String getKey() {	
			return "get directories";
		}
	}

	/**
	 * This class deleting a regular expression
	 * The Command gets the expression, and removing it from the match table in DB.
	 */
	public class removeExpressionCommand extends ImpCommand
	{
		String expression;
		public String getExpression() {
			return expression;
		}
		public void setExpression(String expression) {
			this.expression = expression;
		}
		public Command clone() {
			return new removeExpressionCommand();
		}
		public void execute() 
		{
			insertToLogCommand c = new insertToLogCommand();
			c.setOperation("The regular expression  "+getExpression()+"  had been removed");
			c.execute();
			dirMan.deleteRegExp(getExpression());
		}

		public String getKey() {	
			return "remove exp";
		}
	}

	/**
	 * This class adding a new regular expression
	 * The Command gets the expression, and adding it to the match table in DB.
	 */
	public class addExpressionCommand extends ImpCommand
	{
		public Command clone() {
			return new addExpressionCommand();
		}
		public void execute() 
		{
			insertToLogCommand c = new insertToLogCommand();
			c.setOperation("The regular expression  "+getTag()+"  had been added");
			c.execute();
			dirMan.addExp(getTag());
		}

		public String getKey() {	
			return "add exp";
		}
	}

	/**
	 * This class returns all tags of selected file
	 * The Command gets the {@link Path} of the file, and returns an {@link ArrayList} 
	 * of all it's tags.
	 */
	public class getTagCommand extends ImpCommand
	{
		ArrayList<String> array = new ArrayList<String>(); 

		public Command clone() {
			return new getTagCommand();
		}
		public void execute() 
		{
			if (filesMan.getTags(getPathOnString()) != null)
				array.addAll(filesMan.getTags(getPathOnString()));
		}
		public String getKey() {	
			return "get tag";
		}
		public ArrayList<String> getArray() {	
			return array;
		}
	}

	/**
	 * This class removes all tags from selected file
	 * The Command gets the {@link Path} of the file, and removes all it's tags.
	 */
	public class removeTagsFromFileCommand extends ImpCommand
	{

		public Command clone() {
			return new removeTagsFromFileCommand();
		}
		public void execute() 
		{
			filesMan.removeAllTagFromFile(getPathOnString());
		}
		public String getKey() {	
			return "remove tags from file";
		}
	}
}
